using System;
using System.Collections.Generic;

namespace xmldict {
#region DictAdapter
	public class DictAdapter:IMinimalDict {
		private IDictionary<string, object> source;

		public DictAdapter():this(new Dictionary<string, object>()){}

		public DictAdapter(IDictionary<string, object> source){
			this.source = source;
		}


		public int Count {
			get{
				return source.Count;
			}
		}

		public void Update(IMinimalDict other) {
			if (other == null) {
				return;
			}
			foreach (string key in other.Keys){
				this[key] = other[key];
			}
		}

		public void Update(Dictionary<string, object> other){
			if (other == null) {
				return;
			}
			foreach (string key in other.Keys){
				this[key] = other[key];
			}
		}
		public void Clear(){
			source.Clear();
		}
		
		public void CreateValue(string key){
		}
		public object NewValue(string key) {
			return null;
		}
       public bool TryGetValue(string key, out object value){
			return source.TryGetValue(key, out value);		
		}

		public void Remove(string key) {
			source.Remove(key);
		}

		public ICollection<string> Keys{
			get {
				return source.Keys;
			}
		}

		public object this [string key] {
			get {
				return source[key];
			}
			set {
				source[key] = value;
			}
		}
		
		
		public bool ContainsKey(string key) {
			return source.ContainsKey(key);
		}
		
		public void Add(string key, object value) {
			source.Add(key, value);
		}
		
		public override string ToString()
		{
			return source.ToString();
		}

	}
#endregion	
#region ListAdapter
	public class ListAdapter:IMinimalList {
		private IList<object> source;
		public ListAdapter():this(new List<object>()){}
		public ListAdapter(IList<object> source){
			this.source = source;
		}
		public bool IsReadOnly{get{ return source.IsReadOnly;}}
		public int Count{get{return source.Count;}}
		public object this[int index] {get{return source[index];}}
		public void Add(object data){source.Add(data);}
	}
	
#endregion	
#region MappedDict

	public class MappedDict:IDict {

		private IDictionary<string, string> map;
		private IDict source;
		public MappedDict(IDict source){
			this.source = source;
			map = new SortedDictionary<string, string>();			
		}

		public void updateMapping(IDictionary<string, string> other ){
			foreach (string key in other.Keys){
				map[key] = other[key];
			}
		}
		private string realkey(string key) {
			if (map.ContainsKey(key)){
				return map[key];
			} else {
				return key;
			}
		}
		
		public int Count {
			get{
				return source.Count;
			}
		}

		public void Update(IMinimalDict other) {
			if (other == null) {
				return;
			}
			foreach (string key in other.Keys){
				this[realkey(key)] = other[key];
			}
		}

		public void Update(Dictionary<string, object> other){
			if (other == null) {
				return;
			}
			foreach (string key in other.Keys){
				source[realkey(key)] = other[key];
			}
		}
		public void Clear(){
			source.Clear();
		}
		
		public void CreateValue(string key){
			source.CreateValue(realkey(key));
		}
		
		public object NewValue(string key) {
			return source.NewValue(realkey(key));
		}
		
       public bool TryGetValue(string key, out object value){
			return source.TryGetValue(realkey(key), out value);
		}

		public void Remove(string key) {
			source.Remove(realkey(key));
		}

		public ICollection<string> Keys{
			get {
				HashSet<string> k = new HashSet<string>(source.Keys);
				k.ExceptWith(map.Values);
				k.UnionWith(map.Keys);
				return k;
			}
		}

		public object this [string key] {
			get {
				return source[realkey(key)];
			}
			set {
				source[realkey(key)] = value;
			}
		}
				
		public bool ContainsKey(string key) {
			return source.ContainsKey(realkey(key));
		}
		
		public void Add(string key, object value) {
			source.Add(realkey(key), value);
		}
		
		public override string ToString()
		{
			return source.ToString();
		}
		
		private string[] m(string[] source) {
			string[] result = new string[source.Length];
			for( int i = 0;i< source.Length;i++){
				result[i]=realkey(source[i]);
			}
			return result;
		} 
		
		public void addAllowed(params string[] keys)
		{
			source.addAllowed(m(keys));
		}
		
		public void delAllowed(params string[] keys)
		{
			source.delAllowed(m(keys));
		}
		
		public void addReadonly(params string[] keys)
		{
			source.addReadonly(m(keys));
		}
		
		public void delReadonly(params string[] keys)
		{
			source.delReadonly(m(keys));
		}
		
		public bool keyAllowed(string key)
		{
			return source.keyAllowed(realkey(key));
		}
		
		public bool keyReadonly(string key)
		{
			return source.keyReadonly(realkey(key));
		}
		
		public bool keyValid(string key)
		{
			return source.keyValid(realkey(key));
		}
	}
#endregion		
}

